import subprocess
import asyncio
import aiohttp
from colorama import init, Fore, Style
# Fore.BLACK 黑色
# Fore.RED 红色
# Fore.GREEN 绿色
# Fore.YELLOW 黄色
# Fore.BLUE 蓝色
# Fore.MAGENTA 品红
# Fore.CYAN 蓝绿色
# Fore.WHITE 白色
# Fore.RESET 重置
# Style.RESET_ALL 风格全部重置

modules_info = {
    "Password_Cracking/brute_force_zip": "Brute force ZIP file passwords.",
    "Password_Cracking/Dictionary_Attack": "Dictionary attack on ZIP file passwords.",
    "Social_engineering/visitor_logger": "Log visitor information with a Flask web server.",
    "Social_engineering/QR_Visitor_Tracker": "Generate a QR code to record visitor information.",
    "Network_scanning/Arp_scanning": "Scan the local network using ARP.",
    "Network_scanning/path_scanner": "Scan paths on a web server.",
    "Network_scanning/Subdomain_enumeration": "Enumerate subdomains of a given domain.",
    "Information_gathering/Host_discovery": "Discover active hosts in a specified network.",
    "Information_gathering/information_gathering": "Gather comprehensive system and network information.",
    "Information_gathering/iot_device_scanner": "Scan and identify IoT devices on the network.",
    "Information_gathering/python_whois": "Perform a WHOIS query on a domain.",
    "Information_gathering/website_fingerprint": "Fingerprint a website using Wappalyzer.",
    "Network_sniffing/arp_spoof": "Perform ARP spoofing attack on the network.",
    "Network_sniffing/dhcp_spoofing": "Perform DHCP spoofing attack on the network.",
    "Network_sniffing/dns_spoofing": "Intercept and spoof DNS responses.",
    "Network_sniffing/icmp_redirect": "Send ICMP redirect messages.",
    "Network_sniffing/mac_flooding": "Send a large number of spoofed ARP requests to perform MAC Flooding.",
    "Network_sniffing/sniffing_tool": "Sniffing tool for analyzing network traffic.",
    "Network_sniffing/Wi-Fi_Sniffing": "Sniff Wi-Fi packets to discover networks and their encryption types.",
    "Port_scanning/Port_scanning": "Scan ports on a specified host.",
    "Port_scanning/python-nmap": "Call nmap to scan the port.",
    "Port_scanning/null_scan": "Using specific flag combinations in the TCP protocol to conduct port scanning.",
    "Port_scanning/fin_scan": "Port scanning is carried out by using FIN flag bit in TCP protocol",
    "Port_scanning/xmas_scan": "One of the scanning techniques used to detect the state of the target host port.",
    "Port_scanning/tcp_connect_scan": "Determine whether the port on the target host is open by trying to establish a complete TCP connection.",
    "Port_scanning/syn_scan": "Use the SYN flag bit of TCP protocol to determine whether the port of the target host is open.",
}

modules_info_cn = {
    "Password_Cracking/brute_force_zip": "暴力破解ZIP文件密码。",
    "Password_Cracking/Dictionary_Attack": "对ZIP文件密码进行字典攻击。",
    "Social_engineering/visitor_logger": "使用Flask Web服务器记录访客信息。",
    "Social_engineering/QR_Visitor_Tracker": "生成二维码记录访客信息。",
    "Network_scanning/Arp_scanning": "使用ARP扫描本地网络。",
    "Network_scanning/path_scanner": "扫描Web服务器上的路径。",
    "Network_scanning/Subdomain_enumeration": "枚举给定域的子域。",
    "Information_gathering/Host_discovery": "发现指定网络中的活动主机。",
    "Information_gathering/information_gathering": "收集全面的系统和网络信息。",
    "Information_gathering/iot_device_scanner": "扫描并识别网络上的IoT设备。",
    "Information_gathering/python_whois": "对域进行WHOIS查询。",
    "Information_gathering/website_fingerprint": "使用Wappalyzer对网站进行指纹识别。",
    "Network_sniffing/arp_spoof": "对网络执行ARP欺骗攻击。",
    "Network_sniffing/dhcp_spoofing": "对网络执行DHCP欺骗攻击。",
    "Network_sniffing/dns_spoofing": "拦截和欺骗DNS响应。",
    "Network_sniffing/icmp_redirect": "发送ICMP重定向消息。",
    "Network_sniffing/mac_flooding": "发送大量伪造的ARP请求以执行MAC洪泛攻击。",
    "Network_sniffing/sniffing_tool": "用于分析网络流量的嗅探工具。",
    "Network_sniffing/Wi-Fi_Sniffing": "嗅探Wi-Fi数据包以发现网络及其加密类型。",
    "Port_scanning/Port_scanning": "扫描指定主机的端口。",
    "Port_scanning/python-nmap": "调用nmap扫描端口。",
    "Port_scanning/null_scan": "使用TCP协议中的特定标志组合进行端口扫描。",
    "Port_scanning/fin_scan": "通过在TCP协议中使用FIN标志位来进行端口扫描",
    "Port_scanning/xmas_scan": "用于检测目标主机端口状态的扫描技术之一。",
    "Port_scanning/tcp_connect_scan": "通过尝试建立完整的TCP连接来确定目标主机的端口是否开放。",
    "Port_scanning/syn_scan": "使用TCP协议的SYN标志位来确定目标主机的端口是否开放。"
}

def list_modules():
    categories = {}
    for module, description in modules_info.items():
        category, module_name = module.split('/', 1)
        if category in categories:
            categories[category].append((module_name, description))
        else:
            categories[category] = [(module_name, description)]

    print(Style.RESET_ALL+Fore.GREEN+"Available modules:"+Style.RESET_ALL)
    for category, modules in categories.items():
        print(Style.RESET_ALL+Fore.GREEN+f"\n{category}:"+Style.RESET_ALL)
        for module, description in modules:
            print(Style.RESET_ALL+Fore.CYAN+f"  {category}/{module}"+" - "+Style.RESET_ALL+Fore.GREEN+f"{description}"+Style.RESET_ALL)

def list_modules_cn():
    categories = {}
    for module, description in modules_info_cn.items():
        category, module_name = module.split('/', 1)
        if category in categories:
            categories[category].append((module_name, description))
        else:
            categories[category] = [(module_name, description)]

    print(Style.RESET_ALL+Fore.GREEN+"模块列表:"+Style.RESET_ALL)
    for category, modules in categories.items():
        print(Style.RESET_ALL+Fore.GREEN+f"\n{category}:"+Style.RESET_ALL)
        for module, description in modules:
            print(Style.RESET_ALL+Fore.CYAN+f"  {category}/{module}"+" - "+Style.RESET_ALL+Fore.GREEN+f"{description}"+Style.RESET_ALL)

async def run_path_scanner(base_url, wordlist_file):
    async def fetch(session, url):
        try:
            async with session.get(url) as response:
                try:
                    content = await response.text(errors='ignore')
                except UnicodeDecodeError:
                    content = ""
                return content, response.status
        except aiohttp.ClientError:
            return None, None

    async def scan_paths(base_url, wordlist):
        valid_paths = []
        other_status_codes = {}
        async with aiohttp.ClientSession() as session:
            tasks = [fetch(session, f"{base_url}/{path}") for path in wordlist]
            results = await asyncio.gather(*tasks)
            for i, (result, status_code) in enumerate(results):
                url = f"{base_url}/{wordlist[i]}"
                if status_code is None:
                    print(f"Request failed: {url}")
                    continue
                print(f"Scanning: {url} - Status code: {status_code}")
                if status_code == 200:
                    valid_paths.append(url)
                elif status_code != 404:
                    if status_code in other_status_codes:
                        other_status_codes[status_code].append(url)
                    else:
                        other_status_codes[status_code] = [url]
        return valid_paths, other_status_codes

    try:
        with open(wordlist_file, 'r') as file:
            wordlist = [line.strip() for line in file.readlines()]
    except FileNotFoundError:
        print(f"Wordlist file {wordlist_file} not found.")
        return

    if not wordlist:
        print("Failed to load wordlist.")
        return

    valid_paths, other_status_codes = await scan_paths(base_url, wordlist)
    print("\nHere are all the valid paths with status code 200:")
    for path in valid_paths:
        print(path)
    print("\nHere are the statistics of other status codes (excluding 404):")
    for status_code, urls in other_status_codes.items():
        print(f"Status code {status_code}:")
        for url in urls:
            print(f"  {url}")

async def run_subdomain_enumeration(base_url, wordlist_file):
    async def fetch(session, url):
        try:
            async with session.get(url) as response:
                try:
                    content = await response.text(errors='ignore')
                except UnicodeDecodeError:
                    content = ""
                return content, response.status
        except aiohttp.ClientError:
            return None, None

    async def scan_subdomains(base_url, wordlist):
        valid_subdomains = []
        other_status_codes = {}
        async with aiohttp.ClientSession() as session:
            tasks = [fetch(session, f"http://{subdomain}.{base_url}") for subdomain in wordlist]
            results = await asyncio.gather(*tasks)
            for i, (result, status_code) in enumerate(results):
                url = f"http://{wordlist[i]}.{base_url}"
                if status_code is None:
                    print(f"Request failed: {url}")
                    continue
                print(f"Scanning: {url} - Status code: {status_code}")
                if status_code == 200:
                    valid_subdomains.append(url)
                elif status_code != 404:
                    if status_code in other_status_codes:
                        other_status_codes[status_code].append(url)
                    else:
                        other_status_codes[status_code] = [url]
        return valid_subdomains, other_status_codes

    try:
        with open(wordlist_file, 'r') as file:
            wordlist = [line.strip() for line in file.readlines()]
    except FileNotFoundError:
        print(f"Wordlist file {wordlist_file} not found.")
        return

    if not wordlist:
        print("Failed to load wordlist.")
        return

    valid_subdomains, other_status_codes = await scan_subdomains(base_url, wordlist)
    print("\nHere are all the valid subdomains with status code 200:")
    for subdomain in valid_subdomains:
        print(subdomain)
    print("\nHere are the statistics of other status codes (excluding 404):")
    for status_code, urls in other_status_codes.items():
        print(f"Status code {status_code}:")
        for url in urls:
            print(f"  {url}")

def run_module(current_module, options):
    if current_module == "Password_Cracking/brute_force_zip":
        zip_file_path = options.get("zip_file_path", "")
        charset = options.get("charset", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
        max_length = options.get("max_length", "4")
        subprocess.run(['python3', 'Password_Cracking/brute_force_zip/brute_force_zip.py', zip_file_path, charset, str(max_length)])
    elif current_module == "Password_Cracking/Dictionary_Attack":
        zip_file_path = options.get("zip_file_path", "")
        dictionary_file_path = options.get("dictionary_file_path", "")
        subprocess.run(['python3', 'Password_Cracking/Dictionary_Attack/Dictionary_Attack.py', zip_file_path, dictionary_file_path])
    elif current_module == "Social_engineering/visitor_logger":
        subprocess.run(['python3', 'Social_engineering/visitor_logger/visitor_logger.py'])
    elif current_module == "Network_scanning/Arp_scanning":
        ip_range = options.get("ip_range", "192.168.0.1/24")
        subprocess.run(['python3', 'Network_scanning/Arp_scanning/Arp_scanning.py', ip_range])
    elif current_module == "Network_scanning/path_scanner":
        base_url = options.get("base_url", "")
        wordlist_file = options.get("wordlist_file", "")
        asyncio.run(run_path_scanner(base_url, wordlist_file))
    elif current_module == "Network_scanning/Subdomain_enumeration":
        base_url = options.get("base_url", "")
        wordlist_file = options.get("wordlist_file", "")
        asyncio.run(run_subdomain_enumeration(base_url, wordlist_file))
    elif current_module == "Information_gathering/Host_discovery":
        network_address = options.get("network_address", "")
        subprocess.run(['python3', 'Information_gathering/Host_discovery/Host_discovery.py', network_address])
    elif current_module == "Information_gathering/information_gathering":
        subprocess.run(['python3', 'Information_gathering/information_gathering/information_gathering.py'])
    elif current_module == "Information_gathering/iot_device_scanner":
        network_range = options.get("network_range", "")
        subprocess.run(['python3', 'Information_gathering/iot_device_scanner/iot_device_scanner.py', network_range])
    elif current_module == "Information_gathering/python_whois":
        domain = options.get("domain", "")
        subprocess.run(['python3', 'Information_gathering/python_whois/python_whois.py', domain])
    elif current_module == "Information_gathering/website_fingerprint":
        url = options.get("url", "")
        subprocess.run(['python3', 'Information_gathering/website_fingerprint/website_fingerprint.py', url])
    elif current_module == "Network_sniffing/arp_spoof":
        target_ip = options.get("target_ip", "")
        gateway_ip = options.get("gateway_ip", "")
        subprocess.run(['python3', 'Network_sniffing/arp_spoof/arp_spoof.py', target_ip, gateway_ip])
    elif current_module == "Network_sniffing/dhcp_spoofing":
        subprocess.run(['python3', 'Network_sniffing/dhcp_spoofing/dhcp_spoofing.py'])
    elif current_module == "Network_sniffing/dns_spoofing":
        choice = options.get("choice", "")
        spoofed_ip = options.get("spoofed_ip", "")
        target_domain = options.get("target_domain", "")
        if choice == "1":
            if not spoofed_ip:
                print("[-] Error: Missing spoofed_ip. Use 'set spoofed_ip <ip>'.")
                return
            print("Starting DNS Spoofing (IP only). Press Ctrl+C to stop.")
            subprocess.run(['python3', 'Network_sniffing/dns_spoofing/dns_spoofing.py', "1", spoofed_ip])
        elif choice == "2":
            if not spoofed_ip or not target_domain:
                print("[-] Error: Missing spoofed_ip or target_domain. Use 'set spoofed_ip <ip>' and 'set target_domain <domain>'.")
                return
            print("Starting DNS Spoofing (IP + domain). Press Ctrl+C to stop.")
            subprocess.run(['python3', 'Network_sniffing/dns_spoofing/dns_spoofing.py', "2", spoofed_ip, target_domain])
        else:
            print(Style.RESET_ALL+Fore.RED+"Invalid choice. Choose 1 or 2.")
    elif current_module == "Network_sniffing/icmp_redirect":
        router_ip = options.get("router_ip", "")
        target_ip = options.get("target_ip", "")
        redirect_ip = options.get("redirect_ip", "")
        subprocess.run(['python3', 'Network_sniffing/icmp_redirect/icmp_redirect.py', router_ip, target_ip, redirect_ip])
    elif current_module == "Network_sniffing/mac_flooding":
        target_ip = options.get("target_ip", "")
        subprocess.run(['python3', 'Network_sniffing/mac_flooding/mac_flooding.py', target_ip])
    elif current_module == "Network_sniffing/sniffing_tool":
        interface = options.get("interface", "")
        subprocess.run(['python3', 'Network_sniffing/sniffing_tool/sniffing_tool.py', interface])
    elif current_module == "Network_sniffing/Wi-Fi_Sniffing":
        interface = options.get("interface", "")
        subprocess.run(['python3', 'Network_sniffing/Wi-Fi_Sniffing/Wi-Fi_Sniffing.py', interface])
    elif current_module == "Port_scanning/Port_scanning":
        host = options.get("host", "")
        port_start = options.get("port_start", "")
        port_end = options.get("port_end", "")
        if not host or not port_start or not port_end:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Missing host, port_start, or port_end. Use 'set host <host>', 'set port_start <port>', and 'set port_end <port>'.")
            return
        subprocess.run(['python3', 'Port_scanning/Port_scanning/Port_scanning.py', host, port_start, port_end])
    elif current_module == "Port_scanning/python-nmap":
        host = options.get("host", "")
        start_port = options.get("start_port", "")
        end_port = options.get("end_port", "")
        if not host or not start_port or not end_port:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Missing host, start_port, or end_port. Use 'set host <host>', 'set start_port <port>', and 'set end_port <port>'.")
            return
        subprocess.run(['python3', 'Port_scanning/python-nmap/python-nmap.py', host, start_port, end_port])
    elif current_module == "Port_scanning/null_scan":
        ip = options.get("ip", "")
        port = options.get("port", "")
        if not ip or not port:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Missing ip or port parameters.Use the command set ip <ip> or set port <port> to add, and use the command options to view parameter information.")
            return
        subprocess.run(['python3', 'Port_scanning/null_scan/null_scan.py', ip, port])
    elif current_module == "Port_scanning/fin_scan":
        ip = options.get("ip", "")
        start_port = options.get("start_port", "")
        end_port = options.get("end_port", "")
        if not ip or not start_port or not end_port:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Please check the parameters'.")
            return
        subprocess.run(['python3', 'Port_scanning/fin_scan/fin_scan.py', ip, start_port, end_port])
    elif current_module == "Port_scanning/xmas_scan":
        ip = options.get("ip", "")
        port = options.get("port", "")
        if not ip or not port:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Missing ip or port parameters.Use the command set ip <ip> or set port <port> to add, and use the command options to view parameter information.")
            return
        subprocess.run(['python3', 'Port_scanning/xmas_scan/xmas_scan.py', ip, port])
    elif current_module == "Port_scanning/tcp_connect_scan":
        ip = options.get("ip", "")
        start_port = options.get("start_port", "")
        end_port = options.get("end_port", "")
        if not ip or not start_port or not end_port:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Missing host, start_port, or end_port. Use 'set host <ip>', 'set start_port <port>', and 'set end_port <port>'.")
            return
        subprocess.run(['python3', 'Port_scanning/tcp_connect_scan/tcp_connect_scan.py', ip, start_port, end_port])
    elif current_module == "Port_scanning/syn_scan":
        ip = options.get("ip", "")
        start_port = options.get("start_port", "")
        end_port = options.get("end_port", "")
        if not ip or not start_port or not end_port:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Missing host, start_port, or end_port. Use 'set host <ip>', 'set start_port <port>', and 'set end_port <port>'.")
            return
        subprocess.run(['python3', 'Port_scanning/syn_scan/syn_scan.py', ip, start_port, end_port])
    elif current_module == "Social_engineering/QR_Visitor_Tracker":
        server = options.get("server", "")
        port = options.get("port", "")
        if not server or not port:
            print(Style.RESET_ALL+Fore.RED+"[-] Error: Missing server_address, Use 'set server <server_address>' or 'set port <server_port>'.")
            return
        subprocess.run(['python3', 'Social_engineering/QR_Visitor_Tracker/QR_Visitor_Tracker.py', server, port])
    else:
        print(f"Module {current_module} not found.")
        return